﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Workflow.ComponentModel;

using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;

namespace EFSPWFActivities
{
    public class ShrinkImage : Activity
    {
        #region Properties and Logging

        public static DependencyProperty __ContextProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__Context",
            typeof(WorkflowContext), typeof(ShrinkImage));
        [Description("Context")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public WorkflowContext __Context
        {
            get
            {
                return ((WorkflowContext)(base.GetValue(__ContextProperty)));
            }
            set
            {
                base.SetValue(__ContextProperty, value);
            }
        }

        public static DependencyProperty QualityProperty = DependencyProperty.Register("Quality",
            typeof(Int32), typeof(ShrinkImage));

        [Description("JPEG Quality")]
        [Category("EF Workflow Activities")]
        [Browsable(true)]
        [DesignerSerializationVisibility
        (DesignerSerializationVisibility.Visible)]
        public Int32 Quality
        {
            get
            {
                return ((Int32)
                (base.GetValue(QualityProperty)));
            }
            set
            {
                base.SetValue(QualityProperty, value);
            }
        }

        //public static DependencyProperty NewVersionProperty = DependencyProperty.Register("NewVersion",
        //    typeof(string), typeof(ShrinkImage));

        //[Description("New Version (yes or no)")]
        //[Category("EF Workflow Activities")]
        //[Browsable(true)]
        //[DesignerSerializationVisibility
        //(DesignerSerializationVisibility.Visible)]
        //public string NewVersion
        //{
        //    get
        //    {
        //        return ((string)
        //        (base.GetValue(NewVersionProperty)));
        //    }
        //    set
        //    {
        //        base.SetValue(NewVersionProperty, value);
        //    }
        //}

        public static void WriteDebugInfoToHistoryLog(SPWeb web, Guid workflow, string description)
        {
#if DEBUG
            WriteInfoToHistoryLog(web, workflow, description);
#endif
        }

        public static void WriteInfoToHistoryLog(SPWeb web, Guid workflow, string description)
        {
            TimeSpan ts = new TimeSpan();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SPWorkflow.CreateHistoryEvent(web, workflow, 0, web.CurrentUser, ts, "ShrinkImage", description, string.Empty);
            });
        }

        #endregion


        //http://geekswithblogs.net/bullpit/archive/2009/04/29/compress-image-files-using-c.aspx

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="path">Path to which the image would be saved.</param> 
        // <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        public static MemoryStream SaveJpeg(Image img, int quality)
        {
            // Encoder parameter for image quality
            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec 
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            MemoryStream objMemoryStream = new System.IO.MemoryStream();
            img.Save(objMemoryStream, jpegCodec, encoderParams);

            return objMemoryStream;
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats 
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec 
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            //string strFilePath = string.Empty;

            WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, @"Quality=" + Quality);
            //WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, @"NewVersion=" + NewVersion);

            SPList objSPList = null;
            SPListItem objSPListItem = null;
            string strFileType = string.Empty;

            if (Quality <= 0 || Quality > 100)
            {
                WriteInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, string.Format("Quality({0}) is invalid", Quality));
                return ActivityExecutionStatus.Faulting;
            }

            try
            {
                using (SPSite objSPSite = new SPSite(__Context.CurrentWebUrl))
                {
                    using (SPWeb objSPWeb = objSPSite.OpenWeb())
                    {
                        objSPWeb.AllowUnsafeUpdates = true;

                        objSPList = objSPWeb.Lists[new Guid(__Context.ListId)];
                        objSPListItem = objSPList.GetItemById(__Context.ItemId);
                        if (objSPListItem.File == null)
                        {
                            WriteInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, string.Format("No file found. CurrentItemUrl={0}", __Context.CurrentItemUrl));
                            return ActivityExecutionStatus.Faulting;
                        }
                        strFileType = Convert.ToString(objSPListItem[SPBuiltInFieldId.File_x0020_Type]);
                        if (strFileType.Equals(@"jpg", StringComparison.InvariantCultureIgnoreCase) == false
                            && strFileType.Equals(@"jpeg", StringComparison.InvariantCultureIgnoreCase) == false
                            && strFileType.Equals(@"tif", StringComparison.InvariantCultureIgnoreCase) == false
                            && strFileType.Equals(@"tiff", StringComparison.InvariantCultureIgnoreCase) == false)
                        {
                            WriteInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, string.Format("invalid file type ({0})", strFileType));
                            return ActivityExecutionStatus.Faulting;
                        }

                        SPFile objSPFile = objSPListItem.File;

                        //byte[] imageData = objSPFile.OpenBinary(SPOpenBinaryOptions.Unprotected);
                        Image myImage = Image.FromStream(objSPFile.OpenBinaryStream(SPOpenBinaryOptions.Unprotected));
                        //strFilePath = string.Format(@"{0}/{1}", objSPWeb.Url, objSPFile.Url);
                        //WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, string.Format("strFilePath={0}, objSPFile.Url={1}", strFilePath, objSPFile.Url));

                        MemoryStream objMemoryStream = null;
                        objMemoryStream = SaveJpeg(myImage, Quality);
                        string strFileUrl = objSPFile.Url;
                        int iPos = strFileUrl.LastIndexOf('.');
                        if (strFileType.Equals(@"tif", StringComparison.InvariantCultureIgnoreCase)
                            || strFileType.Equals(@"tiff", StringComparison.InvariantCultureIgnoreCase)
                            || strFileType.Equals(@"jpeg", StringComparison.InvariantCultureIgnoreCase))
                        {
                            //strFileUrl = strFileUrl.Replace(@".tif", @".jpg");
                            strFileUrl = strFileUrl.Substring(0, iPos) + ".jpg";
                        }
                        bool boolOverWrite = false;
                        if (strFileUrl.Equals(objSPFile.Url, StringComparison.InvariantCultureIgnoreCase))
                        {
                            boolOverWrite = true;
                        }

                        SPFile objSPFileNew = objSPFile.ParentFolder.Files.Add(strFileUrl, objMemoryStream, boolOverWrite);
                        //if (boolOverWrite == false)
                        //{
                        //    objSPFile.Recycle();
                        //}
                    }
                }
                //SPFileSaveBinaryParameters obj

                //if (NewVersion.Equals("no", StringComparison.InvariantCultureIgnoreCase))
                //    {
                //        //item.UpdateOverwriteVersion();
                //        item.SystemUpdate(false);
                //    }
                //    else
                //    {
                //        item.Update();
                //    }
            }
            catch (Exception ex)
            {
                WriteInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, @"ShrinkImage exception.");
                WriteInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, @"ex.Message=" + ex.Message);
                WriteInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, @"ex.StackTrace=" + ex.StackTrace);
                return ActivityExecutionStatus.Faulting;
            }

            WriteDebugInfoToHistoryLog(__Context.Web, __Context.WorkflowInstanceId, @"ShrinkImage activity completed.");
            return ActivityExecutionStatus.Closed;
        }
    }
}
